﻿using System;
using RPC;
using System.IO;
using System.Threading;
using System.Net.Sockets;
using System.Net;

namespace Playground {
	public class Example3 {
		private ManualResetEvent r = new ManualResetEvent(false);//Nothing important, move along
		private int c = 2;//Nothing important, move along
		public Example3() {
			ServerMethod();//Start server
			ClientMethod();

			//nothing special here
			while (c > 0) {
				r.Reset();
				r.WaitOne();
			}
		}
		public void ServerMethod() {
			new Thread(() => {
				NetworkStream stream = null;//Stream which will be used to read messages from.
				RPCManager manager = new RPCManager();//Create RPC Manager
				manager.Scan();//Scan all available messages, might take a while.

				//Inline method for RPCLoginRequest event,
				//It's easier for me to write this way example.
				RPCInvoke<RPCLoginRequest> method = new RPCInvoke<RPCLoginRequest>((RPCLoginRequest msg) => {
					if (msg.Username == "demo") {//Check if username is valid, or use your own fancy validatation method.
						if (msg.Password == "pass123") {//Use fancy hashing mechanism to validate password
							Console.WriteLine("[Server] Got login request event, notifying remote client it's valid data.");
							//RPC Message looks ok, and it has good data.
							//Notify remote client about that.
							RPCLoginResponse response = new RPCLoginResponse() {
								Status = true,//True for OK, False if something is wrong.
							};
							manager.Write(stream,response);//Send message
						}
					}
				});
				manager.AddHandler(method);//Add event
				TcpListener server = new TcpListener(IPAddress.Any,4000);//Just creating tcp server;
				server.Start();
				TcpClient client = server.AcceptTcpClient();//Listen for clients
				Console.WriteLine("[Server] Got new client.");
				stream = client.GetStream();//Get the stream

				RPCMessage obj = null;//Create temp file
				while ((obj = manager.Read(stream)) != null) {//Loop through stream
					manager.RaiseEvent(obj);//Raise event.
				}
				Console.WriteLine("[Server] No more data,clients, quiting.");
				//No more data, stop server, and clean up
				stream.Dispose();
				client.Close();
				server.Stop();


				c -= 1;
				r.Set();
			}).Start();
		}
		public void ClientMethod() {
			new Thread(() => {
				NetworkStream stream = null;//Stream which will be used for sending data.
				RPCManager manager = new RPCManager();//Create RPC Manager
				manager.Scan();//Scan all available messages, might take a while.

				//Connet to remote server
				TcpClient client = new TcpClient();
				for (int i = 0; i < 10; i++) {
					client.Connect(IPAddress.Loopback, 4000);
					if (client.Connected) {
						stream = client.GetStream();//Setup variables.
						new Thread(() => {
							Console.WriteLine("[Client] Requesting login.");
							//Imagination login
							RPCLoginRequest request = new RPCLoginRequest();
							request.Username = "demo";
							request.Password = "pass123";

							manager.Write(stream, request);//Send message

						}).Start();

						RPCMessage msg = null;//Temporary message
						while ((msg = manager.Read(stream)) != null) {
							//We will not use events, just pure parsing, but, RPCManager.AddHandler<T> can take of this.
							if (msg is RPCLoginResponse) {//Oh yes it is.
								RPCLoginResponse response = (RPCLoginResponse)msg;
								Console.WriteLine("[Client] Got response from server, loged in: {0}",response.Status);
								Console.WriteLine("[Client] Disconnecting.");
								break;
							}
						}

						stream.Close();
						stream.Dispose();
						client.Close();






						c -= 1;
						r.Set();
						break;
					} else {
						Console.WriteLine("[Client] Unable to connect to server.");
					}
				}

			}).Start();
		}
	}
}
